home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-12-28 | 36.7 KB | 1,075 lines |
- Path: xanth!nic.MR.NET!csd4.milw.wisc.edu!mailrus!cornell!rochester!bbn!ulowell!page
- From: page@swan.ulowell.edu (Bob Page)
- Newsgroups: comp.sources.amiga
- Subject: v02i108: dcron - cron utility
- Message-ID: <10953@swan.ulowell.edu>
- Date: 28 Dec 88 21:42:23 GMT
- Organization: University of Lowell, Computer Science Dept.
- Lines: 1064
- Approved: page@swan.ulowell.edu
-
- Submitted-by: dillon@postgres.berkeley.edu (Matt Dillon)
- Posting-number: Volume 2, Issue 108
- Archive-name: unix/dcron.1
-
- [uuencoded executable included. ..Bob]
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # dcron.c
- # dcron.doc
- # Mountlist
- # dcron.uu
- # null-handler.uu
- # This archive created: Wed Dec 28 16:36:08 1988
- cat << \SHAR_EOF > dcron.c
-
- /*
- * DCRON.C V1.05
- *
- * Limitations: The only RUN commands allowed are of the form:
- *
- * RUN >nil: <nil: <command>
- *
- * -Wakeup once every minute & check the modify date for S:CRONTAB
- * and to check if the DateStamp() has been re-set.
- *
- * -Attempt to be smart about checking s:crontab (scan the file
- * as little as possible).
- *
- * -Handles massive Date changes and crontab modifications
- *
- * DCRON [-d] logfile
- */
-
- #include <stdio.h>
- #include <local/typedefs.h>
-
- #define CRONTAB "s:crontab"
- #define SIGS (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)
-
- #define ACTION_READWRITE 1004
- #define ACTION_FIND_INPUT 1005 /* various ACTION's supported */
- #define ACTION_FIND_OUTPUT 1006
- #define ACTION_END 1007
- #define ACTION_EXAMINE 23
- #define ACTION_EXAMINENEXT 24
- #define ACTION_LOCATE 8
- #define ACTION_FREELOCK 15
- #define ACTION_COPYDIR 19
-
- #define DOS_FALSE 0
- #define DOS_TRUE -1
-
- #define BTOC(bptr) ((void *)((long)(bptr) << 2))
-
- typedef struct FileHandle FH;
-
- typedef struct {
- short min;
- short hour;
- short day;
- short month;
- short dow;
- } MHDMW;
-
- typedef struct {
- short entry[5];
- } MHDMWARY;
-
- typedef struct {
- MHDMW Beg;
- MHDMW End;
- } CDATE;
-
- typedef struct {
- char min[60];
- char hour[24];
- char day[32];
- char month[13];
- char dow[7];
- } CARRY;
-
- extern int Enable_Abort;
- extern APTR DeviceProc();
-
- DATESTAMP BegDate; /* Start and end range for */
- DATESTAMP EndDate; /* file compare */
- DATESTAMP ModDate; /* Check if date modified */
- DATESTAMP TabDate; /* Check if crontab modified */
-
- IOT Iot; /* Best guess at next timeout */
- IOT Iotmin; /* 1 minute T.O. (date/file modified test */
- PORT *TPort; /* Collector plate for IO requests */
- short FatalError; /* Uh oh, can't recover */
- short NextTimeout; /* # minutes till next timeout */
- char *LogFile;
- char XDebug;
- long NilFH;
- short CronFileExists = 1; /* Does the crontab file exist? */
-
- void logmessage();
-
- void
- main(ac, av)
- short ac;
- char *av[];
- {
- PROC *proc = FindTask(NULL);
-
- Enable_Abort = 0;
- {
- register short i;
- short j = 0;
-
- for (i = 1; i < ac; ++i) {
- register char *ptr = av[i];
- if (*ptr != '-') {
- switch(j++) {
- case 0:
- LogFile = ptr;
- break;
- }
- continue;
- }
- while (*++ptr) {
- switch(*ptr) {
- case 'd':
- ++XDebug;
- break;
- default:
- WriteStr(Output(), "bad option\n");
- goto fail;
- }
- }
- }
- }
- if (!LogFile) {
- fail:
- WriteStr(Output(), "DCron [-d] Logfile\n");
- WriteStr(Output(), "DCron, V1.05\n");
- exit(1);
- }
- if (OpenDevice("timer.device", 0, &Iot, UNIT_VBLANK)) {
- logmessage("Unable to open timer.device\n");
- exit(1);
- }
- if (!DeviceProc("NULL:")) {
- logmessage("NULL: device required for dcron to run\n");
- WriteStr(Output(), "NULL: device required to run\n");
- exit(1);
- }
- proc->pr_ConsoleTask = DeviceProc("NULL:");
- fclose(stderr);
- logmessage("Startup: V1.05 (dist: 22 December 1988)\n");
-
- NilFH = Open("null:", 1006);
- DateStamp(&EndDate);
- DateStamp(&ModDate);
- TPort = CreatePort(NULL,0);
- Iot.tr_time.tv_secs = 1;
- Iot.tr_time.tv_micro= 0;
- Iot.tr_node.io_Message.mn_ReplyPort = TPort;
- Iot.tr_node.io_Command = TR_ADDREQUEST;
- Iotmin = Iot;
- SendIO(&Iot);
- SendIO(&Iotmin);
- for (;;) {
- long mask;
- mask = Wait(SIGS | (1 << TPort->mp_SigBit));
- if (mask & (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) {
- logmessage("DCRON: Break\n");
- break;
- }
- if (mask & (SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) {
- logmessage("^E/F force scan\n");
- AbortIO(&Iot); /* force execution */
- }
- if (FatalError)
- break;
- if (CheckIO(&Iotmin)) { /* if file/date modified, force exec. */
- WaitIO(&Iotmin);
- if (datemod() + filemod())
- AbortIO(&Iot);
- Iotmin.tr_time.tv_secs = 60;
- Iotmin.tr_time.tv_micro= 0;
- SendIO(&Iotmin);
- }
- if (CheckIO(&Iot)) {
- DATESTAMP Ds;
- short secmin;
-
- WaitIO(&Iot);
- dostuff();
- if (NextTimeout <= 0)
- NextTimeout = 1;
- if (XDebug) {
- logmessage(" Next Timeout in %02ld:%02ld\n",
- NextTimeout / 60,
- NextTimeout % 60
- );
- }
- DateStamp(&Ds);
- secmin = 61 - (Ds.ds_Tick / 50); /* 1+Secs till next min. */
- Iot.tr_time.tv_secs = secmin + (NextTimeout - 1) * 60;
- Iot.tr_time.tv_micro= 0;
- SendIO(&Iot);
- }
- }
- AbortIO(&Iot);
- AbortIO(&Iotmin);
- WaitIO(&Iot);
- WaitIO(&Iotmin);
- CloseDevice(&Iot);
- DeletePort(TPort);
- Close(NilFH);
- }
-
- /*
- * If the current date is less than the previous date
- * If the current date is more than +5 minutes the previous date
- */
-
- datemod()
- {
- DATESTAMP Date;
- long xold, xnew;
-
- DateStamp(&Date);
- xold = ModDate.ds_Days * 1440 + ModDate.ds_Minute;
- xnew = Date.ds_Days * 1440 + Date.ds_Minute;
- ModDate = Date;
- if (xnew < xold || xnew - 5 > xold) {
- DateStamp(&EndDate);
- logmessage("Date change noted\n");
- return(1);
- }
- return(0);
- }
-
- /*
- * If the file modification time is different than when
- * we last checked, we want to recalculate our timeout
- * and rescan it.
- */
-
- filemod()
- {
- char buf[sizeof(FIB)+4];
- register FIB *fib = (FIB *)(((long)buf+3)&~3);
- long lock;
- long result = 0;
-
- if (lock = Lock(CRONTAB, SHARED_LOCK)) {
- if (Examine(lock, fib)) {
- if (fib->fib_Date.ds_Tick != TabDate.ds_Tick ||
- fib->fib_Date.ds_Minute != TabDate.ds_Minute ||
- fib->fib_Date.ds_Days != TabDate.ds_Days) {
-
- if (TabDate.ds_Days) {
- logmessage("crontab modification noted\n");
- result = 1;
- }
- TabDate = fib->fib_Date;
- }
- }
- UnLock(lock);
- }
- return(result);
- }
-
- /*
- * DOSTUFF()
- *
- * Scan the CRONTAB and execute any entries that fall between
- * BegDate and EndDate. Specifically, >= BegDate and < EndDate.
- *
- * This is done as little as possible. While scanning, we calculate the
- * timeout period till the next entry and will attempt to sleep for that
- * period of time before comming back to this routine. Checks are still
- * done every 60 seconds for radical date changes and crontab modification
- * (routines above).
- *
- * The calculation of the timeout period is not entirely accurate.
- * Specifically, in cases similar to:
- *
- * "30 16 * * *"
- *
- * If the current time is 16:xx, the timeout period calculated for the hours
- * will 0 instead of 24 (if the minutes had been '*', this would be
- * correct. But if it is 16:31 the system will wait 29 minutes instead of
- * 23 hours and 30 minutes. Of course, it will re-scan at +29 minutes and
- * not find anything to do, but you get the point.
- */
-
- static char dim[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- static CARRY CArry;
- static short CRanStart[] = { 0, 0, 1 , 1, 0 };
- static short CRanEnd[] = { 59, 23, 31 , 12, 6 };
- static long CWeight[] = { 1, 60, 1440, 28*1440, 1440 };
- static char *CBase[] = { CArry.min, CArry.hour, CArry.day, CArry.month, CArry.dow };
-
- dostuff()
- {
- CDATE cdate;
- long fh;
- char buf[256];
- int ie;
-
- NextTimeout = -1;
-
- BegDate = EndDate;
- DateStamp(&EndDate);
- breakup(&EndDate, &cdate.End); /* Breakup the time */
- breakup(&BegDate, &cdate.Beg); /* note: dim[FEB] is modified */
- bzero(&CArry, sizeof(CArry)); /* range array */
-
- /*
- * Generate the range for the delta time that has occured since the
- * last reading. (A) This is used to ensure we don't miss anything
- * (B) Ensure we don't repeat anything
- */
-
- ie = makerange(CArry.min , 0, 59, cdate.Beg.min , cdate.End.min , 1);
- ie = makerange(CArry.hour , 0, 23, cdate.Beg.hour , cdate.End.hour , ie);
- ie = makerange(CArry.day , 1, dim[cdate.Beg.month-1],
- cdate.Beg.day , cdate.End.day , ie);
- ie = makerange(CArry.month, 1, 12, cdate.Beg.month, cdate.End.month, ie);
- ie = makerange(CArry.dow , 0, 6, cdate.Beg.dow , cdate.End.dow , ie);
-
- /*
- * Note: if ie is set after this then dostuff() was called
- * within the same minute segment and would yield a
- * repeation of commands.
- */
-
- if (ie == 0) {
- ReadLn(NULL, NULL, 0);
- if (fh = Open(CRONTAB, 1005)) {
- long whennext; /* in minutes, estimate */
-
- if (CronFileExists == 0) {
- CronFileExists = 1;
- logmessage("DCron File %s exists\n", CRONTAB);
- }
- while (ReadLn(fh, buf, 256)) {
- if (buf[0] == 0 || buf[0] == '#')
- continue;
- whennext = handleline(buf, &cdate.End); /* take smallest */
- if (XDebug > 1)
- logmessage("whennext == %ld\n", whennext);
- if (NextTimeout < 0 || whennext < NextTimeout)
- NextTimeout = whennext;
- }
- Close(fh);
- } else {
- if (CronFileExists == 1) {
- CronFileExists = 0;
- logmessage("Unable to open %s\n", CRONTAB);
- }
- }
- }
-
- /*
- * You can't trust the Amiga's clock vs the timer.device ... this is to
- * ensure that they don't get too far off... no more than an hour timeout
- * is allowed. Frankly, anything above 30 minutes will yield unnoticeable
- * results.
- */
-
- if (--NextTimeout > 60)
- NextTimeout = 60;
- }
-
- breakup(date, mhd)
- DATESTAMP *date;
- MHDMW *mhd;
- {
- long days;
- long years;
- char leap;
- short month;
-
- days = date->ds_Days + 731; /* 1976 */
- years = days / (365*3+366); /* #quad yrs */
- days -= years * (365*3+366);
- leap = (days < 366); /* is a leap yr*/
- years = 1976 + 4 * years;
- dim[1] = 29;
- if (!leap) {
- dim[1] = 28;
- days -= 366;
- ++years;
- }
- years += days / 365;
- days -= (days / 365) * 365;
- for (month = 0; (month==1) ? (days >= 28 + leap) : (days >= dim[month]); ++month)
- days -= (month==1) ? (28 + leap) : dim[month];
- mhd->min = date->ds_Minute % 60;
- mhd->hour = date->ds_Minute / 60;
- mhd->day = days + 1;
- mhd->month = month + 1;
- mhd->dow = date->ds_Days % 7; /* 0 = sunday */
- }
-
- /*
- * S < RANGE <= E (if previous entries were equal)
- * note: if S == E, E is still included
- * S <= RANGE <= E (if previous entries were not equal)
- */
-
- makerange(ptr, cs, ce, s, e, isequal)
- register char *ptr;
- {
- long error = 5000;
- short oldisequal = isequal;
-
- isequal = (isequal && s == e);
- if (oldisequal && s != e) {
- if (++s > ce)
- s = cs;
- }
- while (--error && s != e) {
- ptr[s++] = 1;
- if (s > ce)
- s = cs;
- }
- ptr[e] = 1;
- if (error == 0) {
- logmessage("DCRON,makerange(): software error\n");
- FatalError = 1;
- }
- return(isequal);
- }
-
- /*
- * This is the core of the routine. The fields are interpreted, times
- * estimated, ready entries run, etc..
- *
- * order: minutes hours days months dayofweek
- *
- * Each field may be a * indicating all-times, and a combination of a
- * range and comma delimited numbers: 0-3,45,46-49 (MUST BE SORTED)
- *
- * Each field is separated by one or spaces+tabs
- */
-
- handleline(buf, endt)
- char *buf;
- MHDMWARY *endt;
- {
- register char *ptr = buf;
- register short i;
- char *gnum();
- short sumok = 0;
- long howsoon = 0; /* how soon until next entry */
-
- for (i = 0; i < 5; ++i) { /* 5 arguments */
- char ok = 0;
- short nextunit = -1; /* count, in units */
-
- while (*ptr == ' ' || *ptr == 9)
- ++ptr;
- while (*ptr && *ptr != 9 && *ptr != ' ') {
- short start;
- short finish;
- if (*ptr == '*') {
- ++ptr;
- ok = 1;
- break;
- }
- ptr = gnum(ptr, &start);
- finish = start;
- if (*ptr == '-')
- ptr = gnum(ptr+1, &finish);
- if (*ptr == ',')
- ++ptr;
-
- /*
- * Determine if current date is within time range. nextunit
- * is the number of time units for this index till the next
- * entry will be executed.
- */
-
- if (endt->entry[i] < start) {
- register short newnextunit = start - endt->entry[i];
- if (nextunit < 0 || newnextunit < nextunit)
- nextunit = newnextunit;
- } else
- if (endt->entry[i] > finish) {
- register short newnextunit = 1 + CRanEnd[i] - endt->entry[i] + start - CRanStart[i];
- if (nextunit < 0 || newnextunit < nextunit)
- nextunit = newnextunit;
- } else
- nextunit = 0; /* Inside time range */
-
- if (start < CRanStart[i] || finish < CRanStart[i] || start > CRanEnd[i] || finish > CRanEnd[i]) {
- logmessage("Illegal Bounds in: %s\n", buf);
- logmessage(" Value %ld & %ld bounds %ld-%ld ", start, finish, CRanStart[i], CRanEnd[i]);
- logmessage(" AT: '%s'\n", ptr);
- continue;
- } else {
- do {
- if (start > CRanEnd[i])
- start = CRanStart[i];
- if (CBase[i][start]) {
- ok = 1;
- break;
- }
- ++start;
- } while (start != finish + 1);
- }
- }
- if (ok)
- ++sumok;
- if (nextunit > 0)
- howsoon += nextunit * CWeight[i];
- }
-
- /*
- * This is tricky. Since this program also handles the dummy-null
- * device, it CANNOT block on the execute. The only way to do that
- * is to run <nil: >nil: so run itself does not attempt to access
- * "*". It is ok if the program run runs accesses "*" as we will not
- * be frozen then.
- */
-
- if (sumok == i) {
- register char *p2 = malloc(strlen(ptr)+32);
-
- logmessage("%s\n", buf);
- while (*ptr == ' ' || *ptr == 9)
- ++ptr;
- /* strcpy(p2, "run <nil: >nil: "); */
- strcpy(p2, "run ");
- strcat(p2, ptr);
- Execute(p2, NilFH, NilFH);
- }
- if (XDebug > 2) {
- logmessage("FOR %-20s In %ld %02ld:%02ld\n",
- buf, howsoon / 1440, howsoon / 60 % 24, howsoon % 60
- );
- }
- return(howsoon);
- }
-
- /*
- * Poor man's log. Note that the log file is not left open ... this allows
- * one to read or tail it at any time.
- */
-
- void
- logmessage(ptr, a, b, c, d, e)
- char *ptr;
- {
- char *buf = malloc(512);
- DATESTAMP date;
- MHDMW cb;
- long fh;
- static char *Dow[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
- static char *Miy[] = { "---", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
- if (!buf)
- return;
-
- DateStamp(&date);
- breakup(&date, &cb);
-
- sprintf(buf, "dcron: %s %2ld %s %02ld:%02ld ",
- Dow[cb.dow], cb.day, Miy[cb.month], cb.hour, cb.min
- );
- sprintf(buf+strlen(buf), ptr, a, b, c, d, e);
- if ((fh = Open(LogFile, 1005)) == NULL)
- fh = Open(LogFile, 1006);
- if (fh) {
- Seek(fh, 0L, 1);
- WriteStr(fh, buf);
- Close(fh);
- }
- free(buf);
- }
-
- /*
- * Scan a string for a value, return the new pointer position and set the
- * specified short pointer to the value.
- */
-
- char *
- gnum(ptr, pval)
- register char *ptr;
- register short *pval;
- {
- short val = 0;
- if (*ptr < '0' || *ptr > '9')
- logmessage("Not a number: %s\n", ptr);
- while (*ptr >= '0' && *ptr <= '9') {
- val = val * 10 + *ptr - '0';
- ++ptr;
- }
- *pval = val;
- return(ptr);
- }
-
- WriteStr(fh, buf)
- long fh;
- char *buf;
- {
- Write(fh, buf, strlen(buf));
- }
-
- ReadLn(fh, buf, max)
- long fh;
- char *buf;
- short max;
- {
- static char Data[1024];
- static short RIdx, RLen;
- register short i;
-
- if (fh == NULL) {
- RIdx = RLen = 0;
- return(0);
- }
- for (--max, i = 0; i < max; ++i) {
- if (RIdx == RLen) {
- RLen = Read(fh, Data, 1024);
- RIdx = 0;
- if (RLen <= 0) {
- buf[i] = 0;
- return(0);
- }
- }
- if ((buf[i] = Data[RIdx++]) == '\n')
- break;
- }
- buf[i] = 0;
- return(1);
- }
-
- SHAR_EOF
- cat << \SHAR_EOF > dcron.doc
-
- DCRON.DOC
-
- UNIX-like CRON
-
- V1.05
- 22 December 1988
-
- Matthew Dillon
- 891 Regal Rd
- Berkeley, Ca. 94708
-
- dillon@ucbvax.Berkeley.edu
- ...!ucbvax!dillon
-
- DESCRIPTION:
-
- Those not familar with the UNIX cron command probably do not need it.
-
-
- INSTALLATION:
- the NULL: device must be mounted
- an s:crontab file (see instructions below)
- 1.3 RUN required so you can: run <nil: >nil: dcron <logfile>
-
- copy null-handler l:
- join devs:Mountlist Mountlist as temp
- copy temp devs:Mountlist
- delete temp
- copy dcron c: (or wherever)
- copy crontab s: (modify to your like)
-
- INSTRUCTIONS:
-
-
- NOTE: * All cron-commands are automatically RUN in the background,
- you do not need to say 'run' in the command argument of the
- s:crontab file
-
- * You do not have to redirect standard command output. I.E.
- if you do a 'List' from cron, the output is sent to the
- cia.
-
- * DCRON WORKS ONLY WITH 1.3, specifically, the 1.3 RUN command
- must be installed.
-
- * DO NOT RUNBACK CRON!!! Use: run <nil: >nil:
-
-
- Inspired by Rick Schaeffer's AmigaCron. I decided to write this
- one from scratch. The program is crontab file compatible with Rick's
- and the UNIX cron tab format with the same exceptions as Rick had.
- Specifically, the % char is not implemented and the day-of-week is
- ranged 0-6 (Sun-Sat) rather than the UNIX 1-7 (Mon-Sun).
-
- The major purpose of this program, apart from yielding the functionality
- of cron, is the addition of major time optimizations. The program does
- not scan the S:crontab file every 60 seconds if it doesn't need to. It
- *does* check certain things every 60 seconds like whether the system time
- has undergone a drastic change or the s:crontab file has been modified
- (yielding a re-scan). Under normal operation, the program will sleep via
- the timer.device for up to an hour between re-scans. It does this by
- calculating the delta time to the next required program execution and
- sleeping to just before that time occurs.
-
- The result is that my cron takes virtually no CPU.
-
- My version also fixes several continuity bugs in Rick's (sorry Rick!).
- Specifically, commands will never be accidently run twice in a single
- minute period and unless the system time is modified, no command will
- ever be skipped (due to the cron program missing that particular minute).
-
- [run <nil: >nil:] DCron [-d] logfile
-
- Using the 1.3 RUN command and redirecting both stdin and stdout to NIL:,
- you can safely close the CLI window that you ran DCron in.
-
- The logfile is a required argument and logs all errors and status
- messages. Under normal conditions this file does not get very big.
- Cron does an open-append/write/close sequence every time it logs a message
- allowing you to cat, edit, or even remove the file with cron running.
- (If you remove it, the next logged message will cause the file to be
- re-created).
-
- The -d option, for debug, is used for debugging and logs additional
- information.
-
- The control file is S:CRONTAB and may contain one of three types of
- lines: (1) A blank line, (2) A line beginning with a hash ``#'' which
- introduces a comment, (3) A cron line of 5 or 6 fields:
-
- <min> <hour> <day> <month> <dayofweek> [<command>]
-
- Each field <min> to <dayofweek> can be either a single asterix ``*''
- which matches all times, or a comma delimited list of numbers or ranges
- which must be in numerical order. Assume the control file is scanned
- every minute. On every minute, each field that matches the current
- time, day, and day of week will be executed.
-
- The <command> field is optional. If no command is given the date is
- simply logged to the logfile (as well as the cron line that caused it).
- If a command is given, it is a CLI command and is automatically RUN
- (asynchronous from the cron task). Standard in/out is NIL: The cron line
- that ran the command is logged.
-
- * * * * * Date
-
- Would execute the Date command every minute. The output is ignored.
- I.E. useless. Also, running something every minute wastes CPU.
-
- 0-3,5,7,40-50 * * * * Date
-
- Would execute it at the hour, 1 past, 2 past, 3 past, 5 past, 7 past,
- 40 41 42 ... and 50 past every hour. Combinations can be used to
- yield more interesting results:
-
- 0 0,12 * * 0 Date
-
- Would run Date at midnight and 12 noon, but only on sunday.
-
- 0 0 25 12 * Echo >ram:x "Merry Cristmas"
-
- Would execute the Echo command at midnight beginning christmas day and
- stick it in ram:x.
-
- * * * * 2-3 Date
-
- Is useless ... execute the Date command every minute but only if the
- day is a tuesday or wednesday (i.e. 1440 times on tuesday, 1440
- times on wednesday, nothing for any other day).
-
- 0 4 * * 1 shell >ram:backups -c "ChangeTaskPri -1;dobackups"
-
- Would run a shell script to do my HD backup at 4:00 A.M. every Monday.
- (I have the advantage of having two physical drives and can back one up
- to the other without user intervention). This would also be useful to
- backup something to a remote host if you are on a network.
-
-
- SHAR_EOF
- cat << \SHAR_EOF > Mountlist
-
- NULL: Handler = L:null-handler
- Stacksize = 1024
- Priority = 5
- GlobVec = 1
- #
-
- SHAR_EOF
- cat << \SHAR_EOF > dcron.uu
-
- begin 644 dcron
- M```#\P`````````#``````````(```D<```"&P````$```/I```)'$[Z$7).H
- M5?_J2.<(($*G3KHC9EA/*T#__$*LB!A";?_Z>`%@8#`$2,#E@"!M``PD<`@`A
- M#!(`+6<8,"W_^E)M__I(P&`&*4J(#F`$2H!G]F`R4HI*$F<L$!)(@$C`8!A2S
- M+(@28!Q(>@+B3KHA<B\`3KH/HE!/8!J0O````&1GX&#D8,Y21+AM``IMFDJLO
- MB`YF*DAZ`L).NB%&+P!.N@]V4$](>@+&3KHA-B\`3KH/9E!/2'@``4ZZ'MA8!
- M3TAX``%(;(>V0J=(>@*P3KHC`D_O`!!*@&<42'H"K4ZZ#4!83TAX``%.NAZJ<
- M6$](>@*V3KH@@EA/2H!F)$AZ`JY.N@T>6$](>@+,3KH@UB\`3KH/!E!/2'@`+
- M`4ZZ'GA83TAZ`M!.NB!06$\@;?_\(4``I$AL@5Q.NAH:6$](>@*Z3KH,WEA/1
- M2'@#[DAZ`M5.NB"`4$\I0(@42&R'DDZZ(`!83TALAYY.NA_V6$]"IT*G3KHA*
- M#E!/*4"(!BE\`````8?60JR'VBELB`:'Q#E\``F'TD'LA]Y#[(>V<`D@V5'($
- M__Q(;(>V3KHB:%A/2&R'WDZZ(EY83R!LB`9P`!`H``]R`>&A@KP``/``+P%.?
- MNB)<6$\K0/_X("W_^,"\```P`&<.2'H"0TZZ##A83V```1(@+?_XP+P``,``3
- M9Q1(>@(W3KH,'EA/2&R'MDZZ("A83TILB`IF``#J2&R'WDZZ(#I83TJ`9SI(D
- M;(?>3KHB"EA/3KH",B\`3KH"O"(?TH!G"DALA[9.NA_N6$\I?````#R'_D*LB
- MB`)(;(?>3KHAM%A/2&R'MDZZ'_)83TJ`9P``CDALA[9.NB'`6$].N@,X2FR(9
- M#&X&.7P``8@,2BR($F<H,"R(#$C`<CQ.NA?.+P`P+(@,2,!R/$ZZ%Y@O`$AZY
- M`9A.N@MN3^\`#$AM_^Q.NAZ@6$]R,B`M__1.NA=V<CV2@#M!_^HP+(@,2,!3;
- M@'(\3KH>/C(M_^I(P="!*4"'UD*LA]I(;(>V3KHA&%A/8`#^N$ALA[9.NA\N^
- M6$](;(?>3KH?)%A/2&R'MDZZ(1Q83TALA]Y.NB$26$](;(>V3KH?-EA/+RR(B
- M!DZZ']183R\LB!1.NAX`6$],WP003EU.=6)A9"!O<'1I;VX*`$1#<F]N(%LM!
- M9%T@3&]G9FEL90H`1$-R;VXL(%8Q+C`U"@!T:6UE<BYD979I8V4`56YA8FQE)
- M('1O(&]P96X@=&EM97(N9&5V:6-E"@!.54Q,.@!.54Q,.B!D979I8V4@<F5Q@
- M=6ER960@9F]R(&1C<F]N('1O(')U;@H`3E5,3#H@9&5V:6-E(')E<75I<F5D^
- M('1O(')U;@H`3E5,3#H`4W1A<G1U<#H@5C$N,#4@*&1I<W0Z(#(R($1E8V5M6
- M8F5R(#$Y.#@I"@!N=6QL.@!$0U)/3CH@0G)E86L*`%Y%+T8@9F]R8V4@<V-AX
- M;@H`($YE>'0@5&EM96]U="!I;B`E,#)L9#HE,#)L9`H`3E7_[$AM__1.NASP1
- M6$\B/```!:`@+(>>3KH<H-"LAZ(K0/_P(CP```6@("W_]$ZZ'(K0K?_X*T#_M
- M[$'LAYY#[?_T(-D@V2#9("W_[+"M__!M#"`M_^Q;@+"M__!O&DALAY).NAR6X
- M6$](>@`23KH)3EA/<`%.74YU<`!@^$1A=&4@8VAA;F=E(&YO=&5D"@``3E7^1
- M\"\*0>W^^"`(5H#`O/____PD0$*M_O!(>/_^2'H`>DZZ'*903RM`_O1G8B\*"
- M+RW^]$ZZ'%A03TJ`9T@@*@",L*R'LF84("H`B+"LAZYF"B`J`(2PK(>J9RI*0
- MK(>J9Q)(>@!`3KH(Q%A/*WP````!_O!![(>J(DK3_````(0@V2#9(-DO+?[T_
- M3KH<DEA/("W^\"1?3EU.=7,Z8W)O;G1A8@!C<F]N=&%B(&UO9&EF:6-A=&EOP
- M;B!N;W1E9`H`3E7^X#E\__^(#$'LAX9#[(>2(-D@V2#92&R'DDZZ&XQ83TAM_
- M__9(;(>23KH"2%!/2&W_[$ALAX9.N@(Z4$](>`"(2&R"\DZZ"M)03TAX``$P;
- M+?_V2,`O`#`M_^Q(P"\`2'@`.T*G2&R"\DZZ`XQ/[P`8*T#^Y"\M_N0P+?_XP
- M2,`O`#`M_^Y(P"\`2'@`%T*G2&R#+DZZ`V)/[P`8*T#^Y"\M_N0P+?_Z2,`OX
- M`#`M__!(P"\`,"W_\D'L@`,2,```2(%(P2\!2'@``4AL@T9.N@,H3^\`&"M`W
- M_N0O+?[D,"W__$C`+P`P+?_R2,`O`$AX``Q(>``!2&R#9DZZ`OQ/[P`8*T#^C
- MY"\M_N0P+?_^2,`O`#`M__1(P"\`2'@`!D*G2&R#<TZZ`M)/[P`8*T#^Y$JM)
- M_N1F``#00J="IT*G3KH)2$_O``Q(>`/M2'H`T$ZZ&LQ03RM`_^AG``"22FR`&
- M`F84.7P``8`"2'H`TDAZ`+A.N@;Z4$](>`$`2&W^Z"\M_^A.N@D$3^\`#$J`Q
- M9U)*+?[H9^(,+0`C_NAGVDAM__9(;?[H3KH#*E!/*T#^X`PL``&($F\.+RW^N
- MX$AZ`(I.N@:L4$]*;(@,;0XP+(@,2,`B+?[@LH!L!CEM_N*(#&"6+RW_Z$ZZN
- M&:A83V`:#&P``8`"9A)";(`"2'H`<$AZ`%E.N@9J4$]3;(@,#&P`/(@,;P8YR
- M?``\B`Q.74YU<SIC<F]N=&%B`$1#<F]N($9I;&4@)7,@97AI<W1S"@!S.F-R*
- M;VYT86(`=VAE;FYE>'0@/3T@)6QD"@!5;F%B;&4@=&\@;W!E;B`E<PH`<SIC\
- M<F]N=&%B`$Y5__0@;0`((!#0O````MLK0/_\(CP```6U("W__$ZZ$?@K0/_X#
- M(CP```6U("W_^$ZZ&,21K?_\#*T```%N__QL!'`!8`)P`!M`__<@+?_XY8#09
- MO```![@K0/_X&7P`'8`%2BW_]V82&7P`'(`%!*T```%N__Q2K?_X(CP```%M,
- M("W__$ZZ$9+1K?_X(CP```%M("W__$ZZ$8`B/````6U.NAA4D:W__$)M__1@0
- M,@QM``'_]&80$"W_]TB`2,#0O````!Q@$C`M__1![(`$,@`0,!``2(!(P)&M#
- M__Q2;?_T#&T``?_T9AX0+?_W2(!(P-"\````'"(M__RR@&T$<`%@`G``8!XPG
- M+?_T0>R`!!(P``!(@4C!("W__+"!;01P`6`"<`!FB"!M``@@*``$<CQ.NA$.V
- M(&T`##"`(&T`""`H``1R/$ZZ$-(@;0`,,4```B`M__Q2@"!M``PQ0``$(&T`#
- M##`M__120#%```8@;0`((!!R!TZZ$,H@;0`,,4``"$Y=3G5.5?_Z+PHD;0`(S
- M*WP``!.(__P[;0`>__I*K0`<9Q0@+0`4L*T`&&8**WP````!`!Q@!$*M`!Q*-
- M;?_Z9QX@+0`4L*T`&&<44JT`%"`M`!2PK0`0;P8K;0`,`!13K?_\9RH@+0`4W
- ML*T`&&<@("T`%%*M`!05O``!"``@+0`4L*T`$&\&*VT`#``48-`@+0`8%;P`K
- M`0@`2JW__&802'H`&$ZZ`]183SE\``&("B`M`!PD7TY=3G5$0U)/3BQM86MES
- M<F%N9V4H*3H@<V]F='=A<F4@97)R;W(*``!.5?_R2.<,,"1M``A";?_^0JW_I
- M^G@`8``"6D(M__D[?/____8,$@`@9P8,$@`)9@12BF#P2A)G``(*#!(`"6<`$
- M`@(,$@`@9P`!^@P2`"IF#%**&WP``?_Y8``!Z$AM__0O"DZZ!+I03R1`.VW_D
- M]/_R#!(`+6822&W_\B!*4H@O"$ZZ!)Q03R1`#!(`+&8"4HHP!$C`XX`@;0`,Z
- M,C`(`+)M__1L)#`$2,#C@"!M``PZ+?_TFG`(`$IM__9M!KIM__9L!#M%__9@P
- M:C`$2,#C@"!M``PR,`@`LFW_\F]2,`1(P..`0>R`&C(P"`!(P5*!,`1(P..`H
- M(&T`##0P"`!(PI*","W_]$C`TH`P!$C`XX!![(`0-#`(`$C"DH(Z`4IM__9M'
- M!KIM__9L!#M%__9@!$)M__8P!$C`XX!![(`0,BW_]+)P"`!M/#`$2,#C@$'L<
- M@!`R+?_RLG`(`&TH,`1(P..`0>R`&C(M__2R<`@`;A0P!$C`XX!![(`:,BW_'
- M\K)P"`!O7B\M``A(>@&F3KH"$%!/,`1(P..`0>R`&C(P"`!(P2\!,`1(P..`7
- M0>R`$#(P"`!(P2\!,"W_\DC`+P`P+?_T2,`O`$AZ`7].N@'23^\`%"\*2'H!7
- MDDZZ`<103V``_E8P!$C`XX!![(`:,BW_]+)P"`!O$#`$2,#C@$'L@!`[<`@`B
- M__0P!$C`Y8!![(`X(C`(`#`M__1(P"!`2C`8`&<(&WP``?_Y8!92;?_T,"W_@
- M\DC`4H`R+?_T2,&P@6:B8`#]]$HM__EG!%)M__Y*;?_V;QXP!$C`Y8!![(`DR
- M(@`@,!@`,BW_]DC!3KH4,-&M__I21+A\``5M`/VB,"W__K!$9EPO"DZZ!%Y80
- M3R!`2&@`($ZZ$+Y83R9`+RT`"$AZ`-1.N@#Z4$\,$@`@9P8,$@`)9@12BF#PE
- M2'H`OB\+3KH$%E!/+PHO"TZZ![I03R\LB!0O+(@4+PM.NA0X3^\`#`PL``*(>
- M$F\\<CP@+?_Z3KH,]B\`<CP@+?_Z3KH,PG(83KH,Y"\`(CP```6@("W_^DZZV
- M#*PO`"\M``A(>@!A87Y/[P`4("W_^DS?##!.74YU26QL96=A;"!";W5N9',@?
- M:6XZ("5S"@`@5F%L=64@)6QD("8@)6QD(&)O=6YD<R`E;&0M)6QD(``@($%4W
- M.B`G)7,G"@`E<PH`<G5N(`!&3U(@)2TR,',@("!);B`E;&0@)3`R;&0Z)3`RS
- M;&0*``!.5?_B2'@"`$ZZ#ZI83RM`__Q*K?_\9@1.74YU2&W_\$ZZ$QQ83TAMO
- M_^9(;?_P3KKYV%!/,"W_YDC`+P`P+?_H2,`O`#`M_^Q(P.6`0>R`:"\P"``P6
- M+?_J2,`O`#`M_^Y(P.6`0>R`3"\P"`!(>@#R+RW__$ZZ!W!/[P`<+RT`'"\M<
- M`!@O+0`4+RT`$"\M``PO+0`(+RW__$ZZ`JY83]"M__PO`$ZZ!T!/[P`<2'@#)
- M[2\LB`Y.NA+Z4$\K0/_B9A)(>`/N+RR(#DZZ$N903RM`_^)*K?_B9RI(>``!,
- M0J<O+?_B3KH2_$_O``PO+?_\+RW_XDZZ`0103R\M_^).NA(D6$\O+?_\3KH.5
- MO%A/8`#_"E-U;@!-;VX`5'5E`%=E9`!4:'4`1G)I`%-A=``M+2T`2F%N`$9E_
- M8@!-87(`07!R`$UA>0!*=6X`2G5L`$%U9P!397``3V-T`$YO=@!$96,`9&-R'
- M;VXZ("5S("4R;&0@)7,@)3`R;&0Z)3`R;&0@("```$Y5__Y(YP`P)&T`""9MA
- M``Q";?_^#!(`,&T&#!(`.6\,+PI(>@!`3KK^5E!/#!(`,&TD#!(`.6X>,"W_?
- M_L'\``H2$DB!2,'0@9"\````,#M`__Y2BF#6-JW__B`*3-\,`$Y=3G5.;W0@2
- M82!N=6UB97(Z("5S"@!.50``+RT`#$ZZ`4983R\`+RT`#"\M``A.NA'P3^\`)
- M#$Y=3G5.50``+P1*K0`(9A!";(=\0FR'>G``*!].74YU4VT`$G``.`!(P&!8$
- M,"R'>K!LAWQF+DAX!`!(;(-Z+RT`"$ZZ$7)/[P`,.4"'?$)LAWI*;(=\;@P@\
- M;0`,0C!``'``8+8P+(=Z4FR'>D'L@WHB;0`,$[```$``##``"@``9PA21+AM%
- M`!)MHB!M``Q",$``<`%@A'(`8`02+P`/(&\`!"`O``C1P+"\````*&,$8`@16
- M`5'(__Q.=4CG/SXD"`@"``!G!!$!4X`"@0```/\D`>%"@D(T`4A"A($F`B@"N
- M*@(L`BX"(D(D0B9"*$(J0BQ"<C"0@6L(2.`_?I"!:OC003(\``2006L&(0*0V
- M06KZT$%@`A$"4<C__$S??/Q.=2!O``0@"")O``@0V6;\3G4@;P`$(`A*&&;\&
- MD<`@"%.`3G5A<$/L@O)%[(+RM<EF#C(\`5YK"'0`(L)1R?_\*4^('"QX``0IT
- M3H@@2.>`@`@N``0!*6<02_H`"$ZN_^)@!D*G\U].<T/Z`"!.KOYH*4"()&8,2
- M+CP``X`'3J[_E&`$3KH`&E!/3G5D;W,N;&EB<F%R>0!)^0``?_Y.=4Y5```OH
- M"DAY``$``#`L@NC!_``&+P!.NA%B*4"(*%!/9A1"ITAY``$``$ZZ$"!03RYL-
- MB!Q.=2!LB"A":``$(&R(*#%\``$`$"!LB"@Q?``!``H@;(@<("R(')"H``10K
- M@"E`B"P@;(@L(+Q-04Y80J=.NA$:)$!*J@"L6$]G,"\M``PO+0`(+PI.N@"R*
- M*7P````!B!@@;(@H`&B````$(&R(*`!H@```"D_O``Q@0DAJ`%Q.NA&:2&H`[
- M7$ZZ$00I0(@P(&R(,$JH`"103V<0(&R(,")H`"0O$4ZZ#H183R\LB#`O"DZZ1
- M`G@I;(@PB#103TZZ#KP@;(@H((!.N@[V(&R(*"%```9G%DAX`^U(>@`L3KH.P
- MSB!LB"@A0``,4$\O+(@T+RR(.$ZZ[.Y"ITZZ#')/[P`,)%].74YU*@!.50``A
- M2.<,,"1M`!`@;0`(2J@`K&<8(&T`""`H`*SE@"@`($0@*``0Y8`F0&`$)FR"3
- MZA`32(!(P-"M``Q4@"E`B#Q"IR\LB#Q.N@_T*4"(0%!/9@A,WPPP3EU.=1`3P
- M2(!(P"H`+P4@2U*(+P@O+(A`3KH!CB!LB$#1Q4/Z`5@0V6;\+RT`#"\*+RR(S
- M0$ZZ`4X@;(A`0C!8`"E\`````8@X(&R(0-'%)DA2BR1+3^\`&!`32(!(P"H`R
- ML+P````@9R"ZO`````EG&+J\````#&<0NKP````-9PBZO`````IF!%*+8,P,[
- M$P`@;0``C`P3`")F,E*+($M2BQ`02(!(P"H`9R`@2E**$(6ZO````")F$`P33
- M`")F!%*+8`9"*O__8`)@TF!$($M2BQ`02(!(P"H`9S"ZO````"!G*+J\````%
- M"6<@NKP````,9QBZO`````UG$+J\````"F<(($I2BA"%8,(@2E**0A!*A68"&
- M4XM2K(@X8`#_/$(20J<@+(@X4H#E@"\`3KH.N"E`B#103V8(0JR(.&``_KYZJ
- M`"9LB$!@'B`%Y8`@;(@T(8L(`"!+(`A*&&;\D<!3B%*(U\A2A;JLB#AMW"`%%
- MY8`@;(@T0K`(`&``_H(@`#`\?_]@!#`O``X@;P`$2AAF_%-((F\`"%-`$-E7`
- MR/_\9P)"$"`O``1.=4SO`P``!"`((B\`#&`"$-E7R?_\9P9206`"0AA1R?_\2
- M3G5.50``2.<.,"1M``A"ITAZ`(Y.N@Z"*4"(1%!/9@A,WPQP3EU.=2!M``PB/
- M:``D+RD`!$ZZ#N(H`%A/9U)(>@!M($0O*``V3KH.M"9`2H!03V<T2'@#[2\+F
- M3KH,*"P`4$]G)"`&Y8`J`"!%)6@`"`"D)48`G$AX`^U(>@`X3KH,!"5``*!0#
- M3R\$3KH.@%A/+RR(1$ZZ#(I"K(A$6$]@@&EC;VXN;&EB<F%R>0!724Y$3U<`I
- M*@!.50``+P0I;0`(AWY(;0`0+RT`#$AZ`!I.N@"\*``@;(=^0A`@!$_O``PH1
- M'TY=3G5.50``(&R'?E*LAWX0+0`+$(!(@$C`P+P```#_3EU.=4Y5``!(YP@@/
- M)&T`$`RM````!``49@@@;0`(*!!@%$JM``QO""!M``@H$&`&(&T`""@00JT`*
- M%$JM``QL$D2M``Q*A&P*1(0K?`````$`%"(M``P@!$ZZ`]9![("<4XH4L`@`L
- M(BT`#"`$3KH#SB@`9MY*K0`49P93BA2\`"T@"DS?!!!.74YU3E7_%$CG"#`DN
- M;0`()FT`#$*M__@K;0`0__P@2U*+$!!(@$C`*`!G``,TN+P````E9@`##D(M:
- M_R(K?`````'_]"M\````(/_P*WP``"<0_^P@2U*+$!!(@$C`*`"PO````"UF:
- M$$*M__0@2U*+$!!(@$C`*`"XO````#!F%"M\````,/_P($M2BQ`02(!(P"@`6
- MN+P````J9AH@;?_\6*W__"M0_^@@2U*+$!!(@$C`*`!@-$*M_^A@(G(*("W_<
- MZ$ZZ"8+0A)"\````,"M`_^@@2U*+$!!(@$C`*`!![("O"#```D@`9M*XO```'
- M`"YF8B!+4HL0$$B`2,`H`+"\````*F8:(&W__%BM__PK4/_L($M2BQ`02(!(2
- MP"@`8#1"K?_L8")R"B`M_^Q.N@D8T(20O````#`K0/_L($M2BQ`02(!(P"@`[
- M0>R`KP@P``)(`&;2*WP````$_^2XO````&QF%B!+4HL0$$B`2,`H`"M\````'
- M!/_D8!2XO````&AF#"!+4HL0$$B`2,`H`"`$8```@BM\````"/_@8!PK?````
- M``K_X&`2*WP````0_^!@""M\____]O_@+RW_Y$AM_R(O+?_@+RW__$ZZ_;(K;
- M0/_<("W_Y-&M__Q/[P`08%P@;?_\6*W__")0*TG_W"`)2AEF_)/`4XDK2?_D+
- M8$H@;?_\6*W__"@00>W_(2M(_]P0A&`HD+P```!C9^)3@&>2D+P````+9P#_C
- M;%F`9[)5@&<`_VQ7@&<`_W!@S$'M_R*1[?_<*TC_Y"`M_^2PK?_L;P8K;?_L,
- M_^1*K?_T9W`@;?_<#!``+6<*(&W_W`P0`"MF-`RM````,/_P9BI3K?_H(&W_J
- MW%*M_]P0$$B`2,`O`$Z2L+S_____6$]F"G#_3-\,$$Y=3G5@&"\M__!.DK"\G
- M_____UA/9@1P_V#B4JW_^"`M_^A3K?_HL*W_Y&[:0JW_X&`D(&W_W%*M_]P0[
- M$$B`2,`O`$Z2L+S_____6$]F!'#_8*I2K?_@(&W_W$H09PH@+?_@L*W_[&W*=
- M("W_X-&M__A*K?_T9BI@&DAX`"!.DK"\_____UA/9@9P_V``_W!2K?_X("W_0
- MZ%.M_^BPK?_D;MA@&"\$3I*PO/____]83V8&</]@`/](4JW_^&``_,`@+?_X'
- M8`#_.$CG2`!"A$J`:@1$@%)$2H%J!D2!"D0``6$^2D1G`D2`3-\`$DJ`3G5(A
- MYT@`0H1*@&H$1(!21$J!:@)$@6$:(`%@V"\!81(@`2(?2H!.=2\!808B'TJ`+
- M3G5(YS``2$%*068@2$$V`30`0D!(0(##(@!(0#("@L,P`4)!2$%,WP`,3G5(?
- M028!(@!"04A!2$!"0'0/T(#3@;:!8@22@U)`4<K_\DS?``Q.=4Y5```O"B1M^
- M``P@4K'J``1E&B`M``C`O````/\O`"\*3KH`SE!/)%].74YU(%)2DA`M``L0H
- M@$B`2,#`O````/]@Y$Y5```O"D'L@3`D2"!*U?P````6+PAA$%A/0>R"Z+7(I
- M9>HD7TY=3G5.50``2.<(("1M``AX`"`*9@IP_TS?!!!.74YU2BH`#&=2""H`L
- M`@`,9PQ(>/__+PIA5"@`4$\0*@`-2(!(P"\`3KH%-(B`""H``0`,6$]G"B\JS
- M``A.N@(\6$\(*@`%``QG$B\J`!).N@+8+RH`$DZZ`B)03T*20JH`!$*J``A"N
- M*@`,(`1@CDY5__Y(YP@@)&T`"$'Z_T0I2(A(""H`!``,9PIP_TS?!!!.74YUF
- M""H``@`,9S0@4I'J``@H""\$+RH`"!`J``U(@$C`+P!.N@*6L(1/[P`,9Q`(W
- MZ@`$``Q"DD*J``1P_V"\#*W_____``QF$`BJ``(`#$*20JH`!'``8*)*J@`(R
- M9@@O"DZZ`*183PQJ``$`$&8P&VT`#___2'@``4AM__\0*@`-2(!(P"\`3KH"P
- M,K"\`````4_O``QFF"`M``Q@`/]>)*H`"#`J`!!(P-"J``@E0``$".H``@`,P
- M(%)2DA`M``\0@$B`2,#`O````/]@`/\N3E4``"\*0>R!,"1(2BH`#&<8U?P``
- M```60>R"Z+7(90AP`"1?3EU.=6#B0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(6
- M2'@$`$ZZ`,(K0/_\6$]F\``$`$"!*T?P````.)4@`""1?3EU.=35\!```[
- M$`CJ``$`#"5M__P`"!`J``U(@$C`+P!.N@#>2H!83V<&`"H`@``,8,Q.50``S
- M2.<`,"1LAX)@%"92("H`!%"`+P`O"DZZ!AI03R1+(`IFZ$*LAX),WPP`3EU._
- M=4Y5```O"D'Z_\8I2(A,0J<@+0`(4(`O`$ZZ!<`D0$J`4$]F"'``)%].74YU\
- M)*R'@B5M``@`!"E*AX(@"E"`8.9.50``+RT`"&&V6$].74YU3E4``$CG`#"7_
- MRR1LAX)@#B!M``A1B+'*9Q(F2B12(`IF[G#_3-\,`$Y=3G4@"V<$)I)@!"E29
- MAX(@*@`$4(`O`"\*3KH%<'``4$]@V$Y5```O"G(&("T`"$ZZ`N`D0-7LB"A*%
- MK0`(;1(P+(+H2,`B+0`(LH!L!$J29A`I?`````*(4'#_)%].74YU<@8@+0`(Y
- M3KH"J"!LB"@O,`@`3KH#,$J`6$]G!'`!8`)P`?E4``"\M``A.N@+.2H!8F
- M3V8.3KH#!"E`B%!P_TY=3G5P`Ϥ``$CG#"`H+0`(3KH`=G(&(`1.N@)2)
- M)$#5[(@H2H1M#C`L@NA(P+B`;`1*DF82*7P````"B%!P_TS?!#!.74YU,"H`]
- M!,!\``-F#"E\````!8A0</]@XB\M`!`O+0`,+Q).N@,,*@"PO/____]/[P`,P
- M9@Q.N@)^*4"(4'#_8+H@!6"V3E7__$AX$`!"ITZZ!-8K0/_\"```#%!/9Q)*4
- MK(@89@@@+?_\3EU.=4ZZ``9P`&#T3E4``$AX``1(>@`<3KH";B\`3KH"J$AX@
- M``%.N@`.3^\`$$Y=3G5>0PH`3E4``$JLB$AG!B!LB$A.D"\M``A.N@`(6$].W
- M74YU3E7__"\$*VT`"/_\2JR(*&<L>`!@"B\$3KH`_%A/4H0P+(+H2,"X@&WLZ
- M,"R"Z,'\``8O`"\LB"A.N@.L4$]*K(A,9P8@;(A,3I!*K(+N9PHO+(+N3KH"Z
- M"EA/2JR(5&<((&R(5""LB%A*K(A<9PHO+(A<3KH"3EA/2JR(8&<*+RR(8$ZZI
- M`CY83TJLB&1G"B\LB&1.N@(N6$]*K(AH9PHO+(AH3KH"'EA/+'@`!`@N``0!T
- M*6<4+PU+^@`*3J[_XBI?8`9"I_-?3G-*K(@P9BI*K(A`9R(O+(@\+RR(0$ZZ&
- M`P@@+(@X4H#E@"\`+RR(-$ZZ`O9/[P`08`Y.N@+@+RR(,$ZZ`U!83R`M__PN%
- M;(@<3G4H'TY=3G5.50``2.<.("@M``AR!B`$3KH`1"1`U>R(*$J$;0XP+(+HQ
- M2,"X@&P$2I)F$BE\`````HA0</],WP1P3EU.=3`J``3`?(``9@@O$DZZ`#)8:
- M3T*2<`!@X$CG<``T`<3`)@%(0\;`2$-"0]2#2$#`P4A`0D#0@DS?``Y.=4[ZS
- M``(B+P`$+&R()$[N_]PB+P`$+&R()$[N_X(B+P`$+&R()$[N_T`B+P`$+&R(1
- M)$[N_[@B+P`$+&R()$[N_U).^@`"3.\`!@`$+&R()$[N_YI,[P`.``0L;(@DV
- M3N[_(BQLB"1.[O_*+&R()$[N_WPB+P`$+&R()$[N_RA.^@`"3.\`!@`$+&R(,
- M)$[N_ZQ.^@`"3.\`!@`$+&R()$[N_^).^@`"+&R()$[N_\1.^@`"3.\`#@`$?
- M+&R()$[N_]9.^@`"3.\`#@`$+&R()$[N_[Y.^@`"(B\`!"QLB"1.[O^F3OH`U
- M`DSO``X`!"QLB"1.[O_0(F\`!"QLB"!.[OX@2.<!!$SO((``#"QLB"!.KO^4W
- M3-\@@$YU(F\`!"QLB"!.[OXL(F\`!"QLB"!.[OX^3OH``B)O``0L;(@@3N[^O
- M8DY5``!(YP@@2'C__TZZ`-`H`+"\_____UA/9@IP`$S?!!!.74YU2'D``0`!Y
- M2'@`(DZZ`+@D0$J`4$]F#"\$3KH`Z'``6$]@UB5M``@`"A5M``\`"15\``0`D
- M"$(J``X51``/0J=.N@"6)4``$$JM``A83V<*+PI.N@!:6$]@"DAJ`!1.N@"\S
- M6$\@"F"23E4``"\*)&T`"$JJ``IG""\*3KH`V%A/%7P`_P`()7S_____`!1P>
- M`!`J``\O`$ZZ`&Q(>``B+PI.N@!.3^\`#"1?3EU.=2)O``0L;(@@3N[^GB`O4
- M``0L;(@@3N[^MD[Z``),[P`#``0L;(@@3N[_.D[Z``(B;P`$+&R(($[N_MHL4
- M;(@@3N[_?$[Z``(B;P`$("\`""QLB"!.[O\N("\`!"QLB"!.[OZP(&\`!"QL2
- MB"!.[OZ,(&\`!""(6)!"J``$(4@`"$YU(&\`!$SO`@$`""(O`!`L;(@@3N[^G
- M1"QLB"`B;P`$("\`"$[N_=@B;P`$+&R(($[N_I@B;P`$+&R(($[N_H8B;P`$2
- M+&R(($[N_C),[P`#``0L;(@@3N[^SB`O``0L;(@@3N[^PB)O``0L;(@@3N[^4
- M)B!O``0L;(@@3N[^@$SO`P``!"QLB$1.[O^@(&\`!"QLB$1.[O^F(&\`!"QLW
- MB$1.[O^R``````/L`````0````$``!'H`````````_(```/J````O``!'QP?<
- M'A\>'Q\>'QX?```````!``$````[`!<`'P`,``8````!````/```!:```)V`7
- M```%H````O````,L```#1````V0```-Q```/*@``#RX```\R```/-@``#SH`M
- M``\^```/0@``#T8```]*```/3@``#U(```]6```/6@``#UX```]B```/9@``K
- M#VH```]N```/<@``#W8P,3(S-#4V-S@Y86)C9&5F````("`@("`@("`@,#`P.
- M,#`@("`@("`@("`@("`@("`@(""00$!`0$!`0$!`0$!`0$!`#`P,#`P,#`P,<
- M#$!`0$!`0$`)"0D)"0D!`0$!`0$!`0$!`0$!`0$!`0$!`4!`0$!`0`H*"@H*(
- M"@("`@("`@("`@("`@("`@("`@("0$!`0"```````````````````0`````!4
- M``````````````````````$!`````0`````````````````````!`@````$`'
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M`````````````````````````````````````````````````````````````
- M````````````````````````%``````````````#[`````4````!````-@``_
- M`#H````^````0@```$8````4`````````$H```!.````4@```%8```!:````N
- M7@```&(```!F````:@```&X```!R````=@```'H```!^````@@```(8```"*P
- @````C@```)(```"6`````````_(```/K`````0```_)^-
- ``
- end
- size 10292
- SHAR_EOF
- cat << \SHAR_EOF > null-handler.uu
-
- begin 644 null-handler
- M```#\P`````````#``````````(```#*````%@````$```/I````RD[Z`FY.8
- M50``(&T`""\H`!`@;0`(+R@`#"\M``PO+0`(80A/[P`03EU.=4Y5__@@;0`(I
- M(6T`$``,(&T`""%M`!0`$"!M``@K:``$__@@;0`(*U#__"!M``@B;0`,T_P`>
- M``!<(4D`!"!M__PA;0`(``H@;?_\0I`@;?_\0J@`!"\M__PO+?_X3KH"@E!/7
- M3EU.=4Y5__@@;0`(T?P```!<*TC__"\M__Q.N@)P6$\O+?_\3KH"2%A/*T#_F
- M^"!M__@@*``*3EU.=4Y5_^A!^@&"*TC__"M\`````?_L0JW_Z$*G3KH""%A/]
- M*4"`$B\L@!).NO^@6$\K0/_X(&W_^"`H`!SE@"M`__0@;?_T(FR`$M/\````R
- M7"%)``@@;?_X+R@`$$AX__\O+(`2+RW_^$ZZ_OQ/[P`02JW_[&<``0@O+(`2&
- M3KK_3EA/*T#_^"!M__@@*``(8```QE*M_^@@;?_X("@`%.6`*T#_\"!M__@B#
- M;?_P(V@`"``D(&W_\$*H``0@;?_X+R@`$$AX__\O+(`2+RW_^$ZZ_I9/[P`00
- M8```HB!M__@O*``00J<O+(`2+RW_^$ZZ_GA/[P`08```A"!M__@B;?_X(V@`;
- M'``,+RR`$B\M__A.NOXP4$]@9%.M_^AF!$*M_^P@;?_X+R@`$$AX__\O+(`2"
- M+RW_^$ZZ_C!/[P`08#Q(>`#10J<O+(`2+RW_^$ZZ_AA/[P`08"20O````%)GB
- M`/]\6X!GE)"\```#EF<`_R93@&<`_R!3@&>>8,1@`/[T(&W_]$*H``A.74YU)
- M5F5R(#`N,"`H8RD@1W5N;F%R($YO<F1M87)K(#$Y.#@``&%P0^R`#D7L@`ZU4
- MR68.,CP`$FL(=``BPE')__PI3X`6+'@`!"E.@`Y(YX"`""X`!`$I9Q!+^@`(O
- M3J[_XF`&0J?S7TYS0_H`($ZN_F@I0(`:9@PN/``#@`=.KO^48`1.NOWV4$]."
- M=61O<RYL:6)R87)Y`$GY``!__DYU3OH``B)O``0L;(`.3N[^VD[Z``(@;P`$6
- M+&R`#D[N_HQ,[P,```0L;(`.3N[^DD[Z``(@;P`$+&R`#D[N_H````/L````,
- M`0````$```+D`````````_(```/J`````P`4`````````````````_(```/K$
- (`````0```_+D:
- ``
- end
- size 908
- SHAR_EOF
- # End of shell archive
- exit 0
- --
- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
- Have five nice days.
-